//
// Created by Administrator on 2024/10/15.
//

#ifndef MESSAGE_FACTORY_HPP
#define MESSAGE_FACTORY_HPP
#include <cstdint>
#include "../protocol/protocol.hpp"

using protocol::JTT809Packet;
using protocol::JTT809Body;
using protocol::JTT809Header;
using protocol::JTT809Bodies;
using protocol::JTT809SubBodies;
using protocol::JTT809LinkType;
using protocol::MessageBodyFactory;
using protocol::SubMessageBodyFactory;

namespace network {
    typedef std::shared_ptr<JTT809Packet> Packet;

    class MessageFactory {
        static inline uint32_t msg_sn_{0};
        static inline uint32_t msg_gnsscenterid_ = 0;
        static inline protocol::byte *version_ = protocol::generateVersionFlag(1, 1, 1);

        static void whether_encrypt(bool &encrypt, uint32_t &key, uint32_t *encrypt_k) {
            if (encrypt_k) {
                key = *encrypt_k;
                encrypt = true;
            }
        }

    public:
        static Packet keep_alive(const JTT809LinkType link_type, const bool reply, uint32_t *encrypt_k = nullptr) {
            auto which_body = [link_type, reply] {
                if (link_type == JTT809LinkType::main && reply)
                    return JTT809Bodies::UP_LINKTEST_RSP;
                if (link_type == JTT809LinkType::subordinate && reply)
                    return JTT809Bodies::DOWN_LINKTEST_RSP;
                if (link_type == JTT809LinkType::main)
                    return JTT809Bodies::UP_LINKTEST_REQ;
                return JTT809Bodies::DOWN_LINKTEST_REQ;
            };

            const std::shared_ptr<JTT809Body> body(MessageBodyFactory::createBody(which_body()));

            return packet(body, encrypt_k);
        }

        static Packet login_to_superior(uint32_t user_id, const std::string &password,
            const std::string &down_link_ip, const uint16_t down_link_port, uint32_t *encrypt_k = nullptr) {
            const auto body = std::make_shared<protocol::JTT809_0x1001>(user_id, password,
                msg_gnsscenterid_, down_link_ip, down_link_port);

            return packet(body, encrypt_k);
        }

        static Packet packet(const std::shared_ptr<JTT809Body>& body, uint32_t *encrypt_k = nullptr) {
            bool encrypt = false;
            uint32_t key;
            whether_encrypt(encrypt, key, encrypt_k);

            const auto header = std::make_shared<JTT809Header>(
                    *body, msg_sn_++, body->msg_id(), msg_gnsscenterid_,
                    version_, encrypt, key, time(nullptr));

            return std::make_shared<JTT809Packet>(*header, body);
        }
    };
}

#endif //MESSAGE_FACTORY_HPP
